﻿using System;
using System.Runtime.Serialization;
using System.Globalization;
using System.Security.Permissions;
using System.Reflection;
using Gencode.VECore;
using Gencode.VECore.VectorShape;
using System.Collections.Generic;

namespace Gencode.VECore.Serialization
{
    /// <summary>
    /// Saves to or loads data from a *.vec file
    /// </summary>
    [Serializable]
    public class VecSerializer : ISerializable
    {
        #region Serialization Support

        private const string serShapeCount = "ShapeCount";
        private const string serLayerCout = "LayerCount";
        private const string serType = "Type";
        private const string serLayerNum = "LayerNum";
        private const string serCanvasWidth = "Width";
        private const string serCanvasHeight = "Height";

        List<CanvasLayer> _layers;
        public List<CanvasLayer> Layers
        {
            get
            {
                return _layers;
            }
            set
            {
                _layers = value;
            }
        }

        double _height = 1.0;
        public double Height
        {
            get
            {
                return _height;
            }
            set
            {
                _height = value;
            }
        }

        double _width = 1.0;
        public double Width
        {
            get
            {
                return _width;
            }
            set
            {
                _width = value;
            }
        }

        public VecSerializer()
        {
        }

        protected VecSerializer(SerializationInfo info, StreamingContext context)
        {
            _layers = new List<CanvasLayer>();



            int lcnt = info.GetInt32(serLayerCout);
            if (lcnt > 0)
            {
                for (int i = 0; i < lcnt; i++)
                    _layers.Add(new CanvasLayer());
            }


            //_shapeList = new DrawList();

            Width = info.GetDouble(serCanvasWidth);
            Height = info.GetDouble(serCanvasHeight);

            int n = info.GetInt32(serShapeCount);
            string typeName;
            VECShape shape;

            for (int i = 0; i < n; i++)
            {
                typeName = info.GetString(
                    String.Format(CultureInfo.InvariantCulture,
                        "{0}{1}",
                    serType, i));

                shape = Assembly.GetExecutingAssembly().CreateInstance(
                    typeName) as VECShape;

                shape.LoadFromStream(info, i);

                int layernum = info.GetInt32(
                String.Format(CultureInfo.InvariantCulture,
                    "{0}{1}",
                    serLayerNum, i));

                _layers[layernum].AddShape(shape);
            }

        }

        /// <summary>
        /// Save object to serialization stream
        /// </summary>
        /// <param name="info"></param>
        /// <param name="context"></param>
        [SecurityPermission(SecurityAction.Demand, SerializationFormatter = true)]
        public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            if (_layers == null)
                throw new Exception("Canvas Layers are not set");


            info.AddValue(serCanvasHeight, Height);
            info.AddValue(serCanvasWidth, Width);

            info.AddValue(serLayerCout, _layers.Count);

            for (int l = 0; l < _layers.Count; l++)
            {
                info.AddValue(serShapeCount, _layers[l].ShapeList.Count);

                int i = 0;

                foreach (VECShape shape in _layers[l].ShapeList)
                {
                    info.AddValue(
                        String.Format(CultureInfo.InvariantCulture,
                            "{0}{1}",
                            serType, i),
                        shape.GetType().FullName);

                    info.AddValue(
                        String.Format(CultureInfo.InvariantCulture,
                            "{0}{1}",
                            serLayerNum, i),
                        l);

                    shape.SaveToStream(info, i);

                    i++;
                }
            }
        }

        #endregion

    }
}
